// 服务ID
const SERVICE_UUID = '11110001-1111-1111-1111-111111111111';
// 固件升级接收特性ID
const WRITE_UPG_UUID = '11110002-1111-1111-1111-111111111111';
// 命令写入特性ID
const WRITE_CMD_UUID = '11110003-1111-1111-1111-111111111111';
// 命令接收特性ID
const NOTIFY_CMD_UUID = '11110003-1111-1111-1111-111111111111';
/**
 * 蓝牙对象
 */
class BLEUtils  {
  /**
   * 设备ID
   */
  public deviceId:string  ="";
  /**
   * 数据接收
   * @param {*} value 二进制数据
   */
  public onRecevice(value: any) {
    //获取接收的数据，转换为8位无符号整型数组
    var data = new Uint8Array(value);
    var hexString = this.bytes2HexString(data);
    console.warn('接收<=',hexString);
  }
  /**
   * 数据发送
   * @param {*} deviceId 设备ID
   * @param {*} value 二进制数据
   */
  public writeData(deviceId:string, value:any) {
    var buffer = new ArrayBuffer(value.length);
    var dv = new DataView(buffer);
    for (var i = 0; i < value.length; i++) {
      dv.setUint8(i, value[i]);
    }
    console.info('发送命令=>',this.bytes2HexString(value));
    wx.writeBLECharacteristicValue({
      characteristicId: WRITE_CMD_UUID,
      deviceId: deviceId,
      serviceId: SERVICE_UUID,
      value: buffer,
      fail: function (e) {
        console.log("write fail",e)
      }
    })
  }
  public writeData2 (deviceId:string, value:any) {
    var buffer = new ArrayBuffer(value.length);
    var dv = new DataView(buffer);
    for (var i = 0; i < value.length; i++) {
      dv.setUint8(i, value[i]);
    }
    wx.writeBLECharacteristicValue({
      characteristicId: WRITE_UPG_UUID,
      deviceId: deviceId,
      serviceId: SERVICE_UUID,
      value: buffer,
      fail: function (e) {
        console.log("write fail",WRITE_UPG_UUID,e)
      }
    })
  }
  /**
   * 将字节数组转换为16进制字符串
   * @param {*} arrBytes 字节数组
   */
  public bytes2HexString (arrBytes:any) {
    var str = "";
    for (var i = 0; i < arrBytes.length; i++) {
      var tmp;
      var num = arrBytes[i];
      if (num < 0) {
        //此处填坑，当byte因为符合位导致数值为负时候，需要对数据进行处理
        tmp = (255 + num + 1).toString(16);
      } else {
        tmp = num.toString(16);
      }
      if (tmp.length == 1) {
        tmp = "0" + tmp;
      }
      str += tmp + " ";
    }
    return str.toUpperCase();
  }
  /**
   * 将16进制字符串转换为字节数组
   * @param {*} hexString 16进制字符串
   */
  public hexString2Bytes(hexString:string) {
    var pos = 0;
    var len = hexString.length;
    if (len % 2 != 0) {
      return null;
    }
    len /= 2;
    var hexA = new Array();
    for (var i = 0; i < len; i++) {
      var s = hexString.substr(pos, 2);
      var v = parseInt(s, 16);
      hexA.push(v);
      pos += 2;
    }
    return hexA;
  }
  /**
   * 从广播包中获取MAC地址
   * @param {*} advertisData 
   */
  public getMacFromAdvertisData (advertisData:any) {
    var hexArr = Array.prototype.map.call(
      new Uint8Array(advertisData),
      function (bit) {
        return ('00' + bit.toString(16)).slice(-2)
      }
    );
    return hexArr.reverse().join(':').substring(0, 17).toUpperCase();
  }
}
/**
 * 数据结果
 */
class DataResultInfo {
  /**
   * 执行结果
   */
  public result: Boolean = true;
  /**
   * 事件类型
   */
  public eventType:string = "";
  /**
   * 消息
   */
  public message:string = "成功";
  /**
   * 数据对象
   */
  public data:any = null;
}
/**
 * WB031型号
 * 升级流程：
 * 1.更新连接间隔
 * 2.更新MTU
 * 3.查询版本号
 * 4.跳入ImageUpdate
 * 5.重连
 * 6.发送dfu_setting
 * 7.发送APP1.bin
 * 8.发送FLASH固件整体校验命令
 * 9.发送激活分区命令
 */
export class Ble051 {
  private BleUtils:BLEUtils = new BLEUtils();
  private deviceId:string  = "";
  private onDeviceFound:any = null
  public onConnectStatus:any = null;
  private minConnectDuration = 6;
  private maxConnectDuration = 0x40;
  private slaveLatency = 2;
  private connectDelay = 0x0200;
  public mtu :number  = 244;
  /**
   * 构造函数
   */
  constructor() {
    var _this = this;
    // 监听发现设备
    wx.onBluetoothDeviceFound((result) => {
      // 过滤设备
      for (var i = 0; i < result.devices.length; i++) {
        var device = result.devices[i];
        var localName = device.localName;
        if (!!localName) {
          var deviceId = device.deviceId;
          var mac = _this.BleUtils.getMacFromAdvertisData(device.advertisData);
          if (_this.onDeviceFound) {
            // 回调
            var data = { name:localName,deviceId: deviceId, mac: mac,rssi:device.RSSI };
            var dataResult = new DataResultInfo();
            dataResult.result = true;
            dataResult.data = data;
            _this.onDeviceFound(dataResult);
          }
        }
      }
    })
    // 监听设备连接状态
    wx.onBLEConnectionStateChange(function (res) {
      console.log("连接状态变化：",res)
      if (_this.onConnectStatus) {
        var dataResult = new DataResultInfo();
        dataResult.result = true;
        dataResult.data = { connectStatus: res.connected };
        _this.onConnectStatus(dataResult);
      }
    });
    // 监听MUT变化
    wx.onBLEMTUChange(function (res) {
      console.log('onBLEMTUChange bluetooth mtu is', res.mtu)
      // 最大值为244
      if (res.mtu - 3 > 244){
        _this.mtu = 244
      } else {
        _this.mtu = res.mtu -3
      }
    })
    //监听数据接收
    wx.onBLECharacteristicValueChange((result) => {
      _this.BleUtils.onRecevice(result.value);
    });
  }
    /**
   * 搜索设备
   * @param {*} onDeviceFound 发现设备回调
   */
  public startDiscovery(onDeviceFound:any) {
    var _this = this;
    _this.onDeviceFound = onDeviceFound;
    // 打开蓝牙适配器
    wx.openBluetoothAdapter({
      success(res) {
        wx.startBluetoothDevicesDiscovery({
          allowDuplicatesKey: true,
          powerLevel: "high",
          success(res) {
          }
        });
      },
      fail(msg) {
        if (_this.onDeviceFound) {
          var dataResult = new DataResultInfo();
          dataResult.result = false;
          dataResult.data = null;
          dataResult.message = "请打开蓝牙并在系统设置中允许微信使用蓝牙的权限";
          _this.onDeviceFound(dataResult);
        }
      }
    })
  };
  /**
   * 关闭搜索
   */
  public stopDiscovery() {
    var _this = this;
    _this.onDeviceFound = null;
    // 停止搜索
    wx.stopBluetoothDevicesDiscovery({
      success: (res) => { },
    });
  };
  /**
   * 连接设备
   * @param {*} deviceId 设备ID
   * @param {*} onConnectStatus 连接状态变化回调
   */
  public connectDevice(deviceId:string, onConnectStatus:any) {
    var _this = this;
    _this.deviceId = deviceId;
    _this.onConnectStatus = onConnectStatus;
    _this.BleUtils.deviceId = deviceId
    // 连接设备
    wx.createBLEConnection({
      deviceId,
      success() {
        let deviceInfo = wx.getDeviceInfo()
        if (deviceInfo.platform == 'android') {
          wx.setBLEMTU({
            deviceId: deviceId,
            mtu: _this.mtu,
            success: res => {
              console.log('调节MTU成功，' + res.mtu);
              _this.mtu = res.mtu
            },
            fail: (res) => {
              console.log('调节失败，直接获取MTU，' + JSON.stringify(res));
              wx.getBLEMTU({
                deviceId: deviceId, 
                success: res => {
                  console.log('获取MTU成功，' + JSON.stringify(res.mtu));
                  _this.mtu = res.mtu
                }, fail: res => {
                  console.log('获取MTU失败，' + JSON.stringify(res));
                }
              })
            }
          })
        } else {
          setTimeout(() => {
            wx.getBLEMTU({
              writeType: 'writeNoResponse',
              deviceId: deviceId, 
              success: res => {
                console.log('iOS获取MTU成功，api的mtu' + JSON.stringify(res.mtu));
                if (res.mtu == 23 ) {//代表该mtu 的api不可用，认为设备mtu为123
                  _this.mtu = 128               
                } else {
                  _this.mtu = res.mtu
                }
                console.log('iOS获取MTU成功，最终的mtu' + JSON.stringify(res.mtu));
              }, fail: res => {
                console.log('获取MTU失败，' + JSON.stringify(res));
              }
            })
          }, 100);
        }
        // 延时获取服务
        setTimeout(() => {
          wx.getBLEDeviceServices({
            deviceId,
            success(res) {
              res.services.forEach(service => {
                if (service.uuid == SERVICE_UUID) {
                  wx.getBLEDeviceCharacteristics({
                    deviceId: deviceId,
                    serviceId: service.uuid,
                    success: function (cs) {
                      cs.characteristics.forEach(charater => {
                        if (charater.uuid == NOTIFY_CMD_UUID) {
                          // 设置通知特性
                          wx.notifyBLECharacteristicValueChange({
                            characteristicId: charater.uuid,
                            deviceId: deviceId,
                            serviceId: SERVICE_UUID,
                            state: true,
                            success: function () {
                              console.info("notify value change:",charater.uuid)
                            },
                            fail: function () {
                              console.log("notify fail",charater.uuid)
                            }
                          });
                        }
                      });
                    },
                    fail: function (e) {
  
                    }
                  });
                }
              });
            }, fail: (e) => {
  
            }
          })
        }, 2500);
      }, fail: (e) => {
        console.log("connect fail",e)
        if (_this.onConnectStatus) {
          var dataResult = new DataResultInfo();
          dataResult.result = true;
          dataResult.message = "设备已断开！";
          dataResult.data = { connectStatus: false };
          _this.onConnectStatus(dataResult);
        }
      }
    });
  };
  /**
   * 断开设备
   */
  public disConnectDevice(callBack:any) {
    var _this = this;
    _this.onConnectStatus = null;
    // 断开连接
    var deviceId = _this.deviceId;
    if(deviceId){
      wx.closeBLEConnection({
        deviceId,
      });
    }
    setTimeout(() => {
      if(callBack){
        callBack()
      }
    }, 2000);
  };
  /**
   * 更新连接间隙
   */
  public updateBleConnectDuration(){
    var buffer = new Array(9)
    // 6 25 0 600
    buffer[0]= 1 & 0xff
    buffer[1]= (this.minConnectDuration >> 8) & 0xff
    buffer[2]= this.minConnectDuration & 0xff
    buffer[3]= (this.maxConnectDuration >> 8) & 0xff
    buffer[4]= this.maxConnectDuration & 0xff
    buffer[5]= (this.slaveLatency >> 8) & 0xff
    buffer[6]= this.slaveLatency & 0xff
    buffer[7]= (this.connectDelay >> 8) & 0xff
    buffer[8]= this.connectDelay & 0xff
    console.log("更新连接间隔")
    this.BleUtils.writeData(this.deviceId, buffer);
  };
  /**
   * 更新MTU
   */
  public updateBleMtu(){
    var buffer = new Array(3)
    buffer[0]= 2 & 0xff
    buffer[1]= (this.mtu >> 8)& 0xff
    buffer[2]= this.mtu & 0xff
    console.log("更新MTU")
    this.BleUtils.writeData(this.deviceId, buffer);
  };
  /**
   * 查询版本号和升级方式
   */
  public selectVersion(){
    var buffer = new Array(1)
    buffer[0]= 3 & 0xff
    console.log("查询版本号")
    this.BleUtils.writeData(this.deviceId, buffer);
  };
  /**
   * FLASH固件整体校验
   */
  public flashCheck(){
    var buffer = new Array(1)
    buffer[0]= 6 & 0xff
    console.log("FLASH固件整体校验")
    this.BleUtils.writeData(this.deviceId, buffer);
  };
  /**
   * 激活分区表和复位
   */
  public activeAndReset(){
    var buffer = new Array(1)
    buffer[0]= 7 & 0xff
    console.log("激活分区表和复位")
    this.BleUtils.writeData(this.deviceId, buffer);
  };
  /**
   * 跳入ImageUpdate
   */
  public jumpToImageUpdate(){
    var buffer = new Array(1)
    buffer[0]= 8 & 0xff
    console.log("跳入ImageUpdate")
    this.BleUtils.writeData(this.deviceId, buffer);
  };
  /**
   * 发送升级文件
   * @param dataArray 升级文件数据
   */
  sendUpgradeData(dataArray:any){
    if(!!dataArray && dataArray.length > 0){
      this.BleUtils.writeData2(this.deviceId, dataArray);
    }
  }
}
